package com.easylive.admin.controller;

import com.easylive.entity.config.AppConfig;
import com.easylive.entity.constants.Constants;
import com.easylive.entity.dto.TokenUserInfoDto;
import com.easylive.entity.dto.VideoPlayInfoDTO;
import com.easylive.entity.enums.DateTimePatternEnum;
import com.easylive.entity.enums.ResponseCodeEnum;
import com.easylive.entity.po.VideoInfoFile;
import com.easylive.entity.request.category.AdminGetSourceReqVO;
import com.easylive.entity.request.category.AdminUploadImageReqVO;
import com.easylive.entity.vo.ResponseVO;
import com.easylive.exception.BusinessException;
import com.easylive.service.VideoInfoFileService;
import com.easylive.utils.DateUtil;
import com.easylive.utils.FFmpegUtils;
import com.easylive.utils.StringTools;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotBlank;
import java.io.*;
import java.util.Date;

/**
 * @Author: yudaxian
 * @Description: admin端文件上传下载控制器
 * @DateTime: 2024/11/5 21:38
 **/
@RestController
@RequestMapping("/file")
@Slf4j
public class FileController extends ABaseController {

    @Resource
    private AppConfig appConfig;

    @Resource
    private FFmpegUtils fFmpegUtils;

    @Resource
    private VideoInfoFileService videoInfoFileService;

    /**
     * 上传图片，返回图片路径，保存的时候将路径保存到数据库中
     * @param reqVO
     * @return
     */
    @RequestMapping("/uploadImage")
    public ResponseVO uploadImage(@Validated AdminUploadImageReqVO reqVO) {

        /**
         * 按月份存放： 202411 202412
         */
        String month = DateUtil.format(new Date(), DateTimePatternEnum.YYYYMM.getPattern());

        /**
         * 因为是管理端，直接上传到正式目录中
         */
        String folder = appConfig.getProjectFolder() + Constants.FILE_FOLDER + Constants.FILE_COVER + month;
        File fileFolder = new File(folder);
        /**
         * 不存在文件夹则创建，在Java中每一步都要判断
         */
        if (!fileFolder.exists()) {
            fileFolder.mkdirs();
        }
        String originalFilename = reqVO.getFile().getOriginalFilename();
        /**
         * 获取上传的文件名，获取后缀，在服务端生成新的文件名，防止重复
         */
        String realName = StringTools.getImageFileName(originalFilename);
        String filePath = folder + "/" + realName;
        try {
            /**
             * SpringBoot会自动上传，这里直接使用transferTo方法将文件保存到指定路径
             */
            reqVO.getFile().transferTo(new File(filePath));
        } catch (IOException e) {
            log.error("上传图片失败{}", e.getMessage());
            throw new BusinessException("上传图片失败");
        }

        if (reqVO.getCreateThumbnail()) {
            // 生成缩略图 FFmpeg
            fFmpegUtils.createImageThumbnail(filePath);
        }

        return getSuccessResponseVO(Constants.FILE_COVER + month + "/" + realName);
    }

    @GetMapping("/getResource")
    public void getResource(AdminGetSourceReqVO reqVO, HttpServletResponse response) {

        if (!StringTools.pathIsOk(reqVO.getSourceName())) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        String fileSuffix = StringTools.getFileSuffix(reqVO.getSourceName());
        /**
         * 判断文件后缀是否合法
         */
        if (fileSuffix == null) {
            throw new BusinessException(ResponseCodeEnum.CODE_600);
        }
        response.setContentType("image/" + fileSuffix.replace(".", ""));
        /**
         * 设置浏览器缓存时间为30天
         */
        response.setHeader("Cache-Control", "max-age=2592000");
        /**
         * 读取文件并输出到浏览器
         * cover/202411/eFyuetVRfzdClgMRFOPqmGFmioMHNs.png
         */
        readFile(response, reqVO.getSourceName());
    }


    /**
     * 通过fileId，读取视频文件，返回m3u8文件
     * @param fileId
     */
    @Transactional(rollbackFor = Exception.class)
    @GetMapping("/videoResource/{fileId}")
    public void videoResource(@PathVariable("fileId") @NotBlank String fileId, HttpServletResponse response) {
        VideoInfoFile videoInfoFile = videoInfoFileService.getVideoInfoFileByFileId(fileId);
        String filePath = videoInfoFile.getFilePath();
        readFile(response, filePath + "/" + Constants.M3U8_NAME);
    }

    /**
     * 获取到m3u8文件，再接着获取ts文件
     * @param fileId
     */
    @GetMapping("/videoResource/{fileId}/{ts}")
    public void videoResourceTs(@PathVariable("fileId") @NotBlank String fileId,
                                @PathVariable("ts") @NotBlank String ts,
                                HttpServletResponse response) {
        VideoInfoFile videoInfoFile = videoInfoFileService.getVideoInfoFileByFileId(fileId);
        String filePath = videoInfoFile.getFilePath();
        readFile(response, filePath + "/" + ts);
    }

    /**
     * 读取文件，作为流输出到浏览器
     * @param response
     * @param filePath
     */
    protected void readFile(HttpServletResponse response, String filePath) {
        File file = new File(appConfig.getProjectFolder() + Constants.FILE_FOLDER + filePath);
        if (!file.exists()) {
            return;
        }
        try (OutputStream out = response.getOutputStream();
             InputStream in = new FileInputStream(file)) {
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
            }
            out.flush();
        } catch (IOException e) {
            log.error("读取文件失败", e);
        }
    }
}
